:- module(user_access, [
        user_affiliation/3,
        user_package_signature/3,
        user_check/2,
        user_update/3,
%% Types
        user_field/1,
        user/1
 ], [assertions,basicmodes,regtypes]).

:- comment(title, "Creating and Consulting User Identifications").
:- comment(subtitle, "AMOS Project").

:- comment(author, "Manuel Carro and the CLIP Group").
:- comment(author, "Facultad de Inform@'{a}tica").
:- comment(author, "Universidad Polit@'{e}cnica de Madrid").
:- comment(author, "@tt{clip@@dia.fi.upm.es}").
:- comment(author, "@tt{http://www.clip.dia.fi.upm.es/}").

:- comment(module, "

Users exist in the system because they are responsible or somehow
linked to resources.  The class @em{user} expresses the minimal
information needed to distinguish among users, by establishing the
identity (i.e., their digital signature) which is used to mark the
packages the user is responsible for, and the organization the user
belongs to.  A user by itself can be the unique participant on an
organization, in which case the organization would consist of a single
individual.


The operations herein included are aimed at creating and consulting
instances of the @em{user} class.  They may change (for
example, to include more operations) should the ontology evolve in
that direction.

@include{three_argument_explanation.lpdoc}

@sp

@include{../Doc/acknowledgements.lpdoc}

@newpage
").

:- include(db('argnamesv/argnamesv')).   % Kludge to use local version
:- use_module(library(sort)).
:- use_module(db(basic_types)).
:- use_module(db(general_check)).

fields_and_types([
        field(affiliation,  (null ; organization)),
        field(signature,    (null ; atom))]).


:- argnames is_a_user(
        affiliation,
        signature).


:- regtype user_field(?Field)

 # "@var{Field} is a field of a user instance.".

user_field(Field):- member(Field, is_a_user$argnames).


:- regtype user(?User) # "@var{User} is a user.".

user(is_a_user${}).

:- pred user_affiliation(User, Affiliation, NewUser):
        user * list(organization) * user

#"@var{Affiliation} is the list of organizations the @var{NewUser}
belongs to.".

user_affiliation(User, Affiliation, NewUser):-
	user_update(User,[affiliation-Affiliation],NewUser).

:- pred user_package_signature(User, Signature, NewUser):
        user * string * user

 #"@var{Signature} is the digital signature with which @var{NewUser}
signs its packages.".

user_package_signature(User, Signature, NewUser):-
	user_update(User,[signature-Signature],NewUser).

:- pred user_check(?User, ?WrongFields):
        user * list(user_fields)

# "The already formed user @var{User} is checked against the
constraints specified in the ontology definition.
@include{check_definition.lpdoc}.".


%user_check(_User, _WrongFields).

user_check(User, WrongFields):-
        fields_and_types(F),
        check_each_field(F, User, WrongFields).

check_each_field([], _User, []).
check_each_field([field(F, T)|Fs], User, W):-
        User = is_a_user${F => V},
        (
            check_field(T, V) ->
            W = RestW
        ;
            W = [F|RestW]
        ),
        check_each_field(Fs, User, RestW).



:- pred user_update(+User, +PairList, ?NewUser):
        user * list(pair) * user

# "It updates @var{User} to give @var{NewUser}.  @var{PairList} is a
list of pairs (see @pred{pair}): dash-separated ground terms
@tt{Field-Value}, which are meant to express the name of a field and
its update value.  @tt{User update} is a general call upon which all
the rest of the @tt{update} calls rely.".

user_update(User, PairList, NewUser):-
        NewUser = is_a_user${},               % New user skeleton
        sort(is_a_user$argnames, AllFields),
        keysort(PairList, SortedPairList),  %% All sorted in same order now
        update(AllFields, SortedPairList, User, NewUser).

update([], _, _, _).
update([Field|Fields], [Field-NewValue|ToUpdate], User, NewUser):-
        !,
        NewUser = is_a_user${Field => NewValue},
        update(Fields, ToUpdate, User, NewUser).
update([Field|Fields], ToUpdate, User, NewUser):-
        User = is_a_user${Field => Value}, 
        NewUser = is_a_user${Field => Value}, 
        update(Fields, ToUpdate, User, NewUser).


:- comment(version_maintenance,on).

:- comment(version(0*1+2,2003/07/04,12:55*18+'CEST'), "Changed
   use_module and include references to use directory aliases.  (Jesus
   Correas Fernandez)").

:- comment(version(0*1+1,2003/02/14,16:28*28+'CET'), "UserAfter to
NewUser (Manuel Carro)").

:- comment(version(0*1+0,2003/02/13,20:49*56+'CET'), "Initial version,
with all interfaces included.  (Manuel Carro)").

